/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution
{
    bool isInTree(TreeNode* t, TreeNode* x)
    {
        if (t == nullptr)
            return t;
        return t == x ||
            isInTree(t->left, x) ||
            isInTree(t->right, x);
    }
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
    {
        if (root == nullptr)
            return root;

        if (root == p || root == q)
            return root;

        bool pInLeft = isInTree(root->left, p);
        bool pInRight = !pInLeft;

        bool qInLeft = isInTree(root->left, q);
        bool qInRight = !qInLeft;

        if ((pInLeft && qInRight) || (pInRight && qInLeft))
        {
            return root;
        }
        else if (pInLeft && qInLeft)
        {
            return lowestCommonAncestor(root->left, p, q);
        }
        else
        {
            return lowestCommonAncestor(root->right, p, q);
        }
    }
};


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution
{
public:
    bool GetPath(TreeNode* root, TreeNode* x, stack<TreeNode*>& path)
    {
        if (root == nullptr)
        {
            return root;
        }
        path.push(root);

        if (root == x)
            return true;

        if (GetPath(root->left, x, path))
            return true;

        if (GetPath(root->right, x, path))
            return true;

        path.pop();
        return false;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
    {
        stack<TreeNode*> ppath, qpath;
        GetPath(root, p, ppath);
        GetPath(root, q, qpath);

        while (ppath.size() != qpath.size())
        {
            if (ppath.size() > qpath.size())
            {
                ppath.pop();
            }
            else
            {
                qpath.pop();
            }
        }

        while (ppath.top() != qpath.top())
        {
            ppath.pop();
            qpath.pop();
        }

        return ppath.top();
    }
};